package com.pxxy.springboot.webcase.controller;

import com.pxxy.springboot.webcase.entity.Book;
import com.pxxy.springboot.webcase.entity.Result;
import com.pxxy.springboot.webcase.service.BookService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/******************
 * @Author yejf
 * @Description TODO
 */
@Controller
@RequestMapping("/book")
public class BookController {

    private static final Logger log = LoggerFactory.getLogger(BookController.class);

    private static final String COVER_UPLOAD_DIR = "static/images/book_cover_img";

    @Autowired
    private BookService bookService;

    /*@ExceptionHandler(value = RuntimeException.class)
    public void handlerException(Exception ex) {
        //此Controller中，任一个打上了 @RequestMapping的方法出现 RuntimeException 异常时，就会回调此方法
        System.out.println("-- BookContorller的handlerException方法被调用了...");
        System.out.println("ex = " + ex);
    }*/

    @RequestMapping("/list.do")
    public String list(Model model) {
        //1. 直接调用业务层来获取业务数据
        final List<Book> books = this.bookService.findAll();
        //2. 把数据绑定到模型当中
        model.addAttribute("BOOK_LIST", books);
        //3. 返回逻辑视图名
        return "book/list";  //最终目的地：/WEB/INF/jsp/book/list.html
    }

    @RequestMapping(value = "/deleteSelect.do", produces = "text/html;charset=utf-8")
    @ResponseBody  //以内容来响应客户端
    //public String deleteSelected(@RequestParam(value = "flags",required = false) List<Integer> idList) {
    public String deleteSelected(@RequestBody List<Integer> idList) {
        log.debug("Spring MVC帮助封装了请求参数 idList："+idList);
        //调用业务方法
        if(this.bookService.deleteSelected(idList) > 0) {
            return "删除成功";  //这个返回值 会写回到 客户端
        } else {
            return "删除失败";
        }
    }

    @RequestMapping(value = "/add.do", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public Object add(HttpServletRequest request, @Valid Book book, BindingResult bindingResult,
                      @RequestParam("coverUrlFile") MultipartFile coverUrl) {
        System.out.println("bindingResult = " + bindingResult);
        //判断 bindingResult是否存在 bean 验证后的错误信息
        if(bindingResult.hasErrors()) {
            //说明验证没有通过，则把错误绑定前端的页面
            final List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for(FieldError fe : fieldErrors) {
                System.out.println(fe.getField()+" => "+fe.getDefaultMessage());
            }
            //return "error";
            return new Result("failure",fieldErrors);
        } else {
            //判断用户是否选择了文件
            if(!coverUrl.isEmpty()) {
                //上传文件
                final String fileName = uploadFile(coverUrl);
                //即使图片上传失败，图书信息 也要写到数据库, 重新设置图书封面信息
                book.setCoverUrl(fileName);
            } else {
                log.warn("用户没有选择上传图书封面...");
            }
            //调用业务层方法，写到数据库中
            this.bookService.save(book);
            //跳转到JSP
            //return book;
            return new Result("success", book);
        }
    }

    @RequestMapping(value = "/delete.do",produces = "text/plain;charset=utf-8")
    @ResponseBody
    public String delete(Integer id) {
        //调用业务方法
        if(this.bookService.delete(id) > 0) {
            return "删除图书成功，id:"+id;
        } else {
            return "删除失败";
        }
    }

    @RequestMapping(value = "/toUpdate.do", produces = "application/json")
    @ResponseBody
    public Book toUpdate(Integer id) {
        //
        return this.bookService.findById(id);
    }

    @RequestMapping(value = "/search.do")
    public String search(@RequestParam(value = "search", required = false)
                                     String search,
                                        Model model) {
        //调用业务层方法
        final List<Book> bookList = this.bookService.findByKeyword(search);
        //
        model.addAttribute("BOOK_LIST",bookList);
        //把查询关键字带回到前端页面
        model.addAttribute("search",search);
        //返回逻辑视图名
        return "book/list";
    }

    @RequestMapping(value = "/update.do", produces = "application/json;charset=utf-8")
    @ResponseBody
    public Object update(@Valid Book book, BindingResult bindingResult,
                         @RequestParam("coverUrlFile") MultipartFile coverUrl) {
        /*System.out.println("book = " + book);
        System.out.println("bindingResult = " + bindingResult);
        System.out.println("coverUrl = " + coverUrl);*/
        if(bindingResult.hasErrors()) {
            //说明验证没有通过，则把错误绑定前端的页面
            final List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for(FieldError fe : fieldErrors) {
                System.out.println(fe.getField()+" => "+fe.getDefaultMessage());
            }
            //return "error";
            return new Result("failure",fieldErrors);
        } else {
            //判断用户是否选择了上传新文件
            if(!coverUrl.isEmpty()) {
                //1. 完成文件的上传
                final String fileName = uploadFile(coverUrl);
                //即使图片上传失败，图书信息 也要写到数据库
                book.setCoverUrl(fileName);
            } else {
                //说明用户没有上传新封面
                System.out.println("用户没有上传新封面...");
            }
            //调用业务层方法，写到数据库中
            this.bookService.update(book);
            //返回一个封装的json对象
            return new Result("success", book);
        }
    }

    /****
     * 文件上传的操作
     * @param coverUrl
     * @return 返回上传后的全新文件名
     */
    private String uploadFile(MultipartFile coverUrl) {

        final String originalFilename = coverUrl.getOriginalFilename();
        //生成一个新的文件名
        String fileName = UUID.randomUUID().toString();
        //获取原来文件的扩展名
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        fileName += suffix;
        //IO流操作
        try {
            final String path = ResourceUtils.getURL("classpath:").getPath();
            // SpringBoot
            File realPath = new File(path, COVER_UPLOAD_DIR);
            if(!realPath.exists()) {
                System.out.println("创建上传的图片目录结构");
                realPath.mkdirs();
            }
            coverUrl.transferTo(new File(realPath,fileName));
            System.out.println("上传成功，文件名为:" + fileName);
        } catch (IOException e) {
            log.error("上传图片失败", e);
            //重新抛出
            throw new RuntimeException(e);
        }
        //
        return fileName;
    }
}
